// file: system/kernel/alarm.c
// autor:jiangxinpeng
// time:2021.1.19
// copyright:(C) 2020-2050 by jiangxinpeng,All right are reserved.

#include <lib/type.h>
#include <lib/list.h>
#include <lib/time.h>
#include <os/schedule.h>
#include <os/alarm.h>
#include <os/task.h>
#include <arch/interrupt.h>

int SysAlarm(uint32_t second)
{
    task_t *cur = cur_task;
    uint32_t oldsecond = cur->alarm.second;

    if (!second)
    {
        cur->alarm.flags = 0;
    }
    else
    {
        cur->alarm.flags = 1;
        cur->alarm.second = second;
        cur->alarm.ticks = HZ;
    }
    return oldsecond;
}

// update alarm ticks if seconds take out send a alarm exception
void AlarmUpdateTicks()
{
    task_t *task = NULL;

    uint32_t eflags=InterruptDisableStore();
    list_traversal_all_owner_to_next(task, &task_global_list, global_list)
    {
        // if current task alarm can used
        if (task->alarm.flags)
        {
            task->alarm.ticks--;
            if (!task->ticks)
            {
                task->alarm.second--;
                if (!task->alarm.second)
                {
                    // send alarm exception
                    ExceptionSend(task->pid, EXC_CODE_ALRM);
                    // alarm close
                    task->alarm.flags = 0;
                }
                // recover alarm ticks
                task->alarm.ticks = HZ;
            }
        }
    }
    InterruptEnableRestore(eflags);
}